package parserdecoder

import (
	"bufio"
	"io"
	"iptv_server/v3/v2_src/utils"
	"iptv_server/v3/v2_src/utils/common"
	"iptv_server/v3/v2_src/utils/orderedmap"
	"strings"
)

func NewParserTXT(sorter common.Sorter, filter common.Filter, mapper common.Mapper) Parser {
	m := &TXT{
		sorter: sorter,
		filter: filter,
		mapper: mapper,
	}
	return m
}

type TXT struct {
	sorter common.Sorter
	filter common.Filter
	mapper common.Mapper
}

func (m *TXT) Parse(reader io.Reader) (*kkv, error) {
	bufferedReader := bufio.NewReader(reader)

	kvs := new_kkv()

	groupName := ""
	count := 0
	for {
		line, err := bufferedReader.ReadString('\n')
		if err != nil {
			break
		}

		count++
		if count > 100000 { //  最多10万行
			break
		}

		line = strings.Trim(line, "\r")
		line = strings.TrimSpace(line)
		if len(line) == 0 {
			continue
		}

		// 4k频道,#genre#
		part0, yes := strings.CutSuffix(line, ",#genre#")
		if yes {
			groupName = part0
		} else {
			// cctv1,http://...#http://....
			n := strings.Index(line, ",")
			channelName := ""
			if n < 0 {
				continue
			} else if n == 0 {
				channelName = UNDEFINED
			} else {
				channelName = line[:n]
			}
			// fmt.Printf("line: %v\n", line)
			channel := line[n+1:]
			channel = strings.TrimSpace(channel)

			//////////////
			//url
			var group *orderedmap.Orderedmap[[]NameUrl]
			var channelLines []NameUrl

			if v, ok := kvs.Get(groupName); ok {
				group = v
			} else {
				group = orderedmap.New[[]NameUrl]()
				kvs.Set(groupName, group)
			}

			if v, ok := group.Get(channelName); ok {
				channelLines = v
			} else {
				channelLines = make([]NameUrl, 0, 10)
				group.Set(channelName, channelLines)
			}

			changed := false
			for _, l1 := range splitChannel(channel) {
				found := false
				for _, l2 := range channelLines {
					if l1 == l2.url {
						found = true
						break
					}
				}
				if !found {
					channelLines = append(channelLines, NameUrl{
						name: channelName,
						url:  l1,
					})
					changed = true
				}
			}

			if changed {
				group.Set(channelName, channelLines)
			}
		}
	}

	utils.Logger.Debugf("[parser] line count: %d (max 100,000)", count)
	kvs = withMapper(kvs, m.mapper)
	kvs = withSorterAndFilter(kvs, m.sorter, m.filter)
	return kvs, nil
}

func splitChannel(line string) []string {
	sp := strings.Split(line, "#")
	ret := make([]string, 0, 10)
	for _, v := range sp {
		v = strings.TrimSpace(v)
		if len(v) < 7 { // http://
			continue
		}
		if utils.IsHttpUrl(v) {
			ret = append(ret, v)
		}
	}
	return ret
}
